try:
    from functools import wraps
except ImportError:
    from django.utils.functional import wraps  # Python 2.3, 2.4 fallback.
from django.shortcuts import get_object_or_404
from django import forms


def owner_required(Model):
    '''
This decorator allows edit for the owner of the record. Snippet applies for every model that has ForeignKey to User. Works in User model too. Works with other decorators as permission_required or similar.

Usage

@permission_required('blogs.change_entry')
@owner_required(Entry)
def manage_entry(request, object_id=None, object=None, can_edit=False):
...

Decorator populates object and can_edit kwargs if object_id present, otherwise just returns original view function.
'''

    def _decorator(func):

        def _closure(request, *args, **kwargs):
            user = request.user
            if kwargs:
                object_id = int(kwargs.values()[0])
                kwargs['object'] = get_object_or_404(Model, pk=object_id)
                if user.is_superuser:
                    kwargs['can_edit'] = True
                else:
                    if user.__class__ == Model:
                        kwargs['can_edit'] = object_id == user.id
                    else:
                        sets = [rel.get_accessor_name() for rel in user._meta.get_all_related_objects() if rel.model == Model]
                        if sets:
                            kwargs['can_edit'] = object_id in [o.id for o in eval('user.%s.all()' % sets[0])]
            return func(request, *args, **kwargs)
        _closure.__name__ = func.__name__
        _closure.__doc___ = func.__doc__
        _closure.__module___ = func.__module__
        return _closure
    return _decorator


def gzip_compress(func):
    """
    Gzip compress an individual view rather than requiring the whole site to
    use the Gzip middleware.
    """

    @wraps(func)
    def dec(request, *args, **kwargs):
        response = func(request, *args, **kwargs)
        from django.middleware.gzip import GZipMiddleware
        gzip_middleware = GZipMiddleware()
        return gzip_middleware.process_response(request, response)
    return dec


def autostrip(cls):
    '''
    Here is a class decorator that allows not to bother with stripping leading and trailing white space
    from user input provided via forms. This could be a temporary solution for an issue addressed in the ticket #6362.
    The documentation is provided in the form of doctest. The decorator works with ModelForm's
    just as well as with ordinary forms.
    Note however that this is not a 100% panacea.
    Your models still could become malformed if theirs data is obtained from another source, not forms. 
    # Few lines to configure the test environment...
    >>> from django.conf import settings
    >>> settings.configure()

    # Lets define a form that will be used for the test. Note last line of this block, thats how
    # we apply ``autostrip`` decorator.
    >>> class PersonForm(forms.Form):
    ...     name = forms.CharField(min_length=2, max_length=10)
    ...     email = forms.EmailField()
    ...     
    ...     def clean_name(self):
    ...         return self.cleaned_data['name'].capitalize()
    >>> PersonForm = autostrip(PersonForm)

    # Lets see how autostrip works against data with leading and trailing whitespace.
    # Autostrip is performed on ``CharField``s and all its descendants such as ``EmailField``,
    # ``URLField``, ``RegexField``, etc.
    >>> form = PersonForm({'name': '  Victor  ', 'email': '  secret@example.ru  '})
    >>> form.is_valid()
    True
    >>> form.cleaned_data
    {'name': u'Victor', 'email': u'secret@example.ru'}

    # ``clean_*`` methods works after stripping, so the letter and not the space is capitalized:
    >>> form = PersonForm({'name': '  victor', 'email': 'zz@zz.zz'})
    >>> form.is_valid()
    True
    >>> form.cleaned_data
    {'name': u'Victor', 'email': u'zz@zz.zz'}

    # min_length constraint is checked after strip, so it is imposible now to shut up validator with
    # dummy spaces
    >>> form = PersonForm({'name': '  E  ', 'email': 'zz@zz.zz'})
    >>> form.is_valid()
    False
    >>> form.errors
    {'name': [u'Ensure this value has at least 2 characters (it has 1).']}

    # max_length constraint is checked after strip as well
    >>> form = PersonForm({'name': '            Victor              ', 'email': 'zz@zz.zz'})
    >>> form.is_valid()
    True
'''
    fields = [(key, value) for key, value in cls.base_fields.iteritems() if isinstance(value, forms.CharField)]
    for field_name, field_object in fields:
        def get_clean_func(original_clean):
            return lambda value: original_clean(value and value.strip())
        clean_func = get_clean_func(getattr(field_object, 'clean'))
        setattr(field_object, 'clean', clean_func)
    return cls
